#include "string.h"
#include "stdio.h"
#include "order_sensor_app.h"
#include "order_sensor_bsp.h"
#include "ti_msp_dl_config.h"
#include "user_main.h"


board_config_t g_board_config = {
    .wifi_ap_ssid = "TP305",
    .wifi_ap_password = "ZhiRui305",
    .pc_ip = "192.168.0.114",
    .pc_udp_port = 8888,
    // .device_type = EQP_TYPE,
    // .device_id = 0x1,
};



static int _uart_check_host_pack_integrity( const uint8_t * buf )
{
    uint8_t XOR = buf[1] ;
    uint8_t i;
    uint8_t buf_total_len = buf[1] + 2;

    if(DEVICE_ID != buf[2])
        return -1;

    if ( UART_HEAD_HOST_TO_SLAVE != buf[0] )
        return -1;

    if ( UART_TAIL != buf[buf_total_len - 1] )
        return -1;

    for( i = 2; i <= buf_total_len - 3; ++i )
        XOR ^= buf[i];

    if ( XOR != buf[buf_total_len - 2] )
        return -1;
    
    return 0;
}


static uint8_t _xor( uint8_t *begin, uint8_t *end )
{
    uint8_t xor_value = *begin;
    uint8_t *p = begin + 1;

    while ( p <= end )
    {
        xor_value ^= *p;
        p++;
    }

    return xor_value;
}


static int _get_wifi_cfg_from_buf( uint8_t *begin, uint8_t *len_out, board_config_t *board_config )
{
    switch ( *begin )
    {
    case CFG_IDX_WIFI_AP_SSID:
        memcpy( board_config->wifi_ap_ssid, (char *)( begin + 1 ), 32 );
        *len_out = 1 + 32;   
        break;

    case CFG_IDX_WIFI_AP_PASSWORD:
        memcpy( board_config->wifi_ap_password, (char *)( begin + 1 ), 32 );
        *len_out = 1 + 32;   
        break;

    case CFG_IDX_PC_IP:
        memcpy( board_config->pc_ip, (char *)( begin + 1 ), 18 );
        *len_out = 1 + 18;   
        break;

    case CFG_IDX_PC_UDP_PORT:
        board_config->pc_udp_port = begin[1] + begin[2] * 256;
        *len_out = 1 + 2;   
        break;

    case CFG_IDX_DEVICE_UDP_PORT:
        board_config->device_udp_port = begin[1] + begin[2] * 256;
        *len_out = 1 + 2;   
        break;

    default:
        return -1;
    }
		return 0;
}

#define UART_WAIT_MS 500 
// 返回值： 0 ： wifi 模块配置成功 。 -1 ：wifi 模块配置失败
int8_t _setup_wifi_udp( board_config_t *board_config , uart_data_t *uart_data )
{
    uint8_t flag;
    int len;

    bsp_uart_clear_recv_buf(uart_data);
    bsp_uart_clear_send_buf(uart_data);
    // 1.1  +++ 退出 数据模式，进入 命令模式
    bsp_timing_setup_wifi_udp( IDLE );
    while( bsp_timing_setup_wifi_udp( RUN ) < 20 );

    len = sprintf( (char *)(uart_data->send_buf) , "+++" );
    uart_data->send_len = len;

    bsp_uart_send( uart_data );

    bsp_timing_setup_wifi_udp( IDLE );
    while( bsp_timing_setup_wifi_udp( RUN ) < 1100 );


    // 1.2 AT+CWMODE：设置 Wi-Fi 模式 (发送两遍，避免在发送 +++ 之前已经为 AT 指令模式的情况)
    for( uint8_t i = 0; i < 2; ++i )
    {
        bsp_uart_clear_recv_buf(uart_data);
        bsp_uart_clear_send_buf(uart_data);

        len = sprintf( (char *)(uart_data->send_buf), "AT+CWMODE=1\r\n" );
        uart_data->send_len = len;
    
        bsp_uart_send( uart_data );

        bsp_timing_setup_wifi_udp( IDLE );
        while( bsp_timing_setup_wifi_udp( RUN ) < UART_WAIT_MS );
    }

    if( strstr( (char *)(uart_data->recv_buf)  , "OK" ) == NULL )
    {   
        return -1;        
    }

    // 1.3 AT+CWQAP：断开与 AP 的连接
    bsp_uart_clear_recv_buf(uart_data);
    bsp_uart_clear_send_buf(uart_data);

    len = sprintf( (char *)(uart_data->send_buf), "AT+CWQAP\r\n" );
    uart_data->send_len = len;

    bsp_uart_send( uart_data );

    bsp_timing_setup_wifi_udp( IDLE );
    while( bsp_timing_setup_wifi_udp( RUN ) < UART_WAIT_MS );

    if( strstr( (char *)(uart_data->recv_buf)  , "OK" ) == NULL )
    {   
        return -1;        
    }

    // 1.4 AT+CWJAP：连接 AP
    bsp_uart_clear_recv_buf(uart_data);
    bsp_uart_clear_send_buf(uart_data);

    len = sprintf( (char *)(uart_data->send_buf), "AT+CWJAP=\"%s\",\"%s\"\r\n",
                   board_config->wifi_ap_ssid,
                   board_config->wifi_ap_password);
    uart_data->send_len = len;

    bsp_uart_send( uart_data );

    bsp_timing_setup_wifi_udp( IDLE );
    while( bsp_timing_setup_wifi_udp( RUN ) < 5000 );

//增加延时
    if( strstr( (char *)(uart_data->recv_buf)  , "OK" ) == NULL )
    {   
        return -1;        
    }

    // 1.5 AT+CIPSTA：查询/设置 ESP32 Station 的 IP 地址
    // TODO : 需要补充此处的代码
    bsp_uart_clear_recv_buf(uart_data);
    bsp_uart_clear_send_buf(uart_data);

    len = sprintf( (char *)(uart_data->send_buf), "AT+CIPSTA?\r\n" );
    uart_data->send_len = len;

    bsp_uart_send( uart_data );

    bsp_timing_setup_wifi_udp( IDLE );
    while( bsp_timing_setup_wifi_udp( RUN ) < UART_WAIT_MS );

    if( strstr( (char *)(uart_data->recv_buf)  , "OK" ) == NULL )
    {   
        return -1;
    }
    else 
    {
        char *ip_begin = strstr((const char *)uart_data->recv_buf, "ip:") + 4;
        char *ip_end   = strstr((const char *)ip_begin, "\"") - 1;
        memcpy(board_config->device_ip, ip_begin, ip_end - ip_begin + 1);
    }

    // 1.6 AT+SAVETRANSLINK： 设置开机进入 TCP 或 UDP 透传模式 信息
    bsp_uart_clear_recv_buf(uart_data);
    bsp_uart_clear_send_buf(uart_data);

    len = sprintf( (char *)(uart_data->send_buf), "AT+SAVETRANSLINK=1,\"%s\",%d,\"UDP\",%d\r\n",
                   board_config->pc_ip,
                   board_config->pc_udp_port,
                   board_config->device_udp_port );
    uart_data->send_len = len;

    bsp_uart_send( uart_data );

    bsp_timing_setup_wifi_udp( IDLE );
    while( bsp_timing_setup_wifi_udp( RUN ) < UART_WAIT_MS );

    if( strstr( (char *)(uart_data->recv_buf)  , "OK" ) == NULL )
    {   
        return -1;        
    }

    // 1.7 AT+RST：重启模块
    bsp_uart_clear_recv_buf(uart_data);
    bsp_uart_clear_send_buf(uart_data);
    
    len = sprintf( (char *)(uart_data->send_buf), "AT+RST\r\n" );
    uart_data->send_len = len;

    bsp_uart_send( uart_data );

    bsp_timing_setup_wifi_udp( IDLE );
    while( bsp_timing_setup_wifi_udp( RUN ) < UART_WAIT_MS + 1000);

    if( strstr( (char *)(uart_data->recv_buf) , "OK" ) == NULL )
    {   
        return -1;        
    }

    bsp_uart_clear_recv_buf(uart_data);
    return 0;

}

static int _uart_deal_cmd_get_device_info( board_config_t *board_config , uart_data_t *uart_data )
{
    // TODO : 需要根据新协议补充打包数据
    uint8_t index = 0;
    uart_data->send_buf[ index++ ] = UART_HEAD_SLAVE_TO_HOST;
    uart_data->send_buf[ index++ ] = 0;
    uart_data->send_buf[ index++ ] = DEVICE_ID;
    uart_data->send_buf[ index++ ] = UART_CMD_GET_DEVICE_INFO;
    uart_data->send_buf[ index++ ] = CMD_IDX_BSP_VERSION;
    uart_data->send_buf[ index++ ] = BSP_VERSION_HEX & 0xFF;
    uart_data->send_buf[ index++ ] = (BSP_VERSION_HEX >> 8) & 0xFF;
    uart_data->send_buf[ index++ ] = (BSP_VERSION_HEX >> 16) & 0xFF;
    uart_data->send_buf[ index++ ] = (BSP_VERSION_HEX >> 24) & 0xFF;

    uart_data->send_buf[ 1 ] = index;

    uart_data->send_buf[ index ] = _xor( &uart_data->send_buf[ 1 ] , &uart_data->send_buf[ index - 1 ] );
    index++;

    uart_data->send_buf[ index++ ] = UART_TAIL;

    uart_data->send_len = index;

    return index;

}

static int _uart_deal_cmd_wifi_config( board_config_t *board_config , uart_data_t *uart_data )
{
    // 从串口接收字符串中解析配置参数，并保存到 board_data 中
    uint8_t *begin = &( uart_data->recv_buf[4] );
    uint8_t len = 0;

    while( begin < &( uart_data->recv_buf[ uart_data->recv_buf[1] - 1 ] ) )
    {
        if( _get_wifi_cfg_from_buf( begin, &len, board_config ) == -1 )
            return -1;
       
        begin += len;
    }

    // 从 board_data 中获取配置参数，并使用 uart1 (g_uart_data_udp) 对 wifi 模块进行配置
    int8_t cfg_result = -1;

    cfg_result = _setup_wifi_udp( board_config , (uart_data_t *)&g_uart_data_udp );


    // 配置 wifi 模块后，打包 配置命令回复数据帧
    // TODO : 需要根据新协议补充打包数据

    uint8_t index = 0;
    uart_data->send_buf[ index++ ] = UART_HEAD_SLAVE_TO_HOST;
    uart_data->send_buf[ index++ ] = 0;
    uart_data->send_buf[ index++ ] = DEVICE_ID;
    uart_data->send_buf[ index++ ] = UART_CMD_WIFI_CONFIG;
    uart_data->send_buf[ index++ ] = CFG_IDX_WIFI_UDP_STATUS;
    uart_data->send_buf[ index++ ] = cfg_result;
    uart_data->send_buf[ index++ ] = CFG_IDX_WIFI_DEVICE_IP;
    
    memcpy( &(uart_data->send_buf[index]), board_config->device_ip, BUF_LEN_PC_UDP_IP );
    index += BUF_LEN_PC_UDP_IP;

    uart_data->send_buf[ 1 ] = index;

    uart_data->send_buf[ index ] = _xor( &uart_data->send_buf[ 1 ] , &uart_data->send_buf[ index - 1 ] );
    index++;

    uart_data->send_buf[ index++ ] = UART_TAIL;

    uart_data->send_len = index;

    return index;
}      


static int _get_cmd_order_from_buf( uint8_t *begin, uint8_t *len_out, uint32_t *board_order_array )
{
    board_order_array[*begin] = begin[1] + (begin[2] << 8) + (begin[3] << 16) + (begin[4] << 24);

    *len_out = 5;
    return 0;
}

int uart_deal_cmd_set_order( uint32_t *board_order_array, uart_data_t *uart_data )
{
    // 从串口接收字符串中解析配置参数，并保存到 board_order_array 中
    uint8_t *begin = &( uart_data->recv_buf[4] );
    uint8_t len = 0;

    while( begin < &( uart_data->recv_buf[ uart_data->recv_buf[1] - 1 ] ) )
    {
        _get_cmd_order_from_buf( begin, &len, board_order_array );
        begin += len;
    }

    ////////////////////////////////////////////////////////////
    uint8_t index = 0;
    uart_data->send_buf[ index++ ] = UART_HEAD_SLAVE_TO_HOST;
    uart_data->send_buf[ index++ ] = 0;
    uart_data->send_buf[ index++ ] = DEVICE_ID;
    uart_data->send_buf[ index++ ] = UART_CMD_SET_ORDER;

    uart_data->send_buf[ 1 ] = index;

    uart_data->send_buf[ index ] = _xor( &uart_data->send_buf[ 1 ] , &uart_data->send_buf[ index - 1 ] );
    index++;

    uart_data->send_buf[ index++ ] = UART_TAIL;


    uart_data->send_len = index;
    return 0;
}

// int uart_deal_upload_data( board_data_t *board_data , uart_data_t *uart_data , board_config_t *board_config)
int uart_deal_cmd_get_sensor( uint32_t *board_sensor_array, uint32_t board_sensor_array_len, uart_data_t *uart_data)
{
    uint8_t index = 0;
    uart_data->send_buf[ index++ ] = UART_HEAD_SLAVE_TO_HOST;
    uart_data->send_buf[ index++ ] = 0;
    uart_data->send_buf[ index++ ] = DEVICE_ID;
    uart_data->send_buf[ index++ ] = UART_CMD_GET_SENSOR;

    for(int i = 0; i < board_sensor_array_len; ++i)
    {
        uart_data->send_buf[ index++ ] = i;
        uart_data->send_buf[ index++ ] = board_sensor_array[i] & 0xFF;
        uart_data->send_buf[ index++ ] = board_sensor_array[i] >> 8 & 0xFF;
        uart_data->send_buf[ index++ ] = board_sensor_array[i] >> 16 & 0xFF;
        uart_data->send_buf[ index++ ] = board_sensor_array[i] >> 24 & 0xFF;
    }

    uart_data->send_buf[ 1 ] = index;

    uart_data->send_buf[ index ] = _xor( &uart_data->send_buf[ 1 ] , &uart_data->send_buf[ index - 1 ] );
    index++;

    uart_data->send_buf[ index++ ] = UART_TAIL;

    uart_data->send_len = index;
    return index;
}

void order_sensor_init( void )
{
    NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN);
    NVIC_EnableIRQ(UART_0_INST_INT_IRQN);

    NVIC_ClearPendingIRQ(UART_1_INST_INT_IRQN);
    NVIC_EnableIRQ(UART_1_INST_INT_IRQN);

}
static int _uart_deal( uint32_t *board_order_array, uint32_t *board_sensor_array, uint32_t board_sensor_array_len, uart_data_t * uart_data )
{
    uint32_t recv_time = 0;
    int ret;

    // DONE : 计时功能合并到一个函数
    recv_time = bsp_timing_uart_receive( uart_data , RUN );

    if( recv_time > 10 && uart_data->recv_flag == UART_FLAG_ONGOING )
    {

        bsp_timing_uart_receive( uart_data , IDLE );
    
        uart_data->recv_flag  = UART_FLAG_FINISHED;
        uart_data->recv_index = 0;
        
        ret = _uart_check_host_pack_integrity( uart_data->recv_buf );
        if ( -1 == ret )
        {
            return -1;
        }

        switch ( uart_data->recv_buf[3] ) {
            case UART_CMD_GET_DEVICE_INFO:
                _uart_deal_cmd_get_device_info( &g_board_config , uart_data );
                break;
                
            case UART_CMD_WIFI_CONFIG:
                _uart_deal_cmd_wifi_config( &g_board_config , uart_data );
                break;

            case UART_CMD_SET_ORDER: 
                uart_deal_cmd_set_order( board_order_array, uart_data );
                break;

            case UART_CMD_GET_SENSOR: 
                uart_deal_cmd_get_sensor( board_sensor_array, board_sensor_array_len, uart_data );
                break;

            default:
                return -1;
        }

        bsp_uart_send( uart_data );
        
        bsp_timing_uart_usb_receive( IDLE );
    }

    return 0;
}

int order_sensor_act( uint32_t *board_order_array, uint32_t *board_sensor_array, uint32_t board_sensor_array_len)
{
    _uart_deal( board_order_array, board_sensor_array , board_sensor_array_len, (uart_data_t *)&g_uart_data_usb );
    _uart_deal( board_order_array, board_sensor_array , board_sensor_array_len, (uart_data_t *)&g_uart_data_udp );

    return 0;
}
